<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd">
<html lang="zh-CN"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><meta http-equiv="Content-Language" content="zh-CN"><link href="stylesheet.css" media="all" rel="stylesheet" type="text/css">
<title>UPDATE</title>
<script> var _hmt = _hmt || []; (function() { var hm = document.createElement("script"); hm.src = "https://hm.baidu.com/hm.js?d286c55b63a3c54a1e43d10d4c203e75"; var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(hm, s); })(); </script>
</head><body class="REFENTRY">
<div>
<table summary="Header navigation table" width="100%" border="0" cellpadding="0" cellspacing="0">
<tr><th colspan="5" align="center" valign="bottom">PostgreSQL 8.2.3 中文文档</th></tr>
<tr><td width="10%" align="left" valign="top"><a href="sql-unlisten.html" accesskey="P">后退</a></td><td width="10%" align="left" valign="top"><a href="sql-unlisten.html">快退</a></td><td width="60%" align="center" valign="bottom"></td><td width="10%" align="right" valign="top"><a href="sql-vacuum.html">快进</a></td><td width="10%" align="right" valign="top"><a href="sql-vacuum.html" accesskey="N">前进</a></td></tr>
</table>
<hr align="LEFT" width="100%"></div>
<h1><a name="SQL-UPDATE"></a>UPDATE</h1>
<div class="REFNAMEDIV"><a name="AEN54985"></a><h2>名称</h2>UPDATE&nbsp;--&nbsp;更新一个表中的行</div>
<a name="AEN54988"></a>
<div class="REFSYNOPSISDIV"><a name="AEN54990"></a><h2>语法</h2>
<pre class="SYNOPSIS">UPDATE [ ONLY ] <tt class="REPLACEABLE"><i>table</i></tt> [ [ AS ] <tt class="REPLACEABLE"><i>alias</i></tt> ]
    SET { <tt class="REPLACEABLE"><i>column</i></tt> = { <tt class="REPLACEABLE"><i>expression</i></tt> | DEFAULT } |
          ( <tt class="REPLACEABLE"><i>column</i></tt> [, ...] ) = ( { <tt class="REPLACEABLE"><i>expression</i></tt> | DEFAULT } [, ...] ) } [, ...]
    [ FROM <tt class="REPLACEABLE"><i>fromlist</i></tt> ]
    [ WHERE <tt class="REPLACEABLE"><i>condition</i></tt> ]
    [ RETURNING * | <tt class="REPLACEABLE"><i>output_expression</i></tt> [ AS <tt class="REPLACEABLE"><i>output_name</i></tt> ] [, ...] ]</pre>
</div>
<div class="REFSECT1"><a name="AEN55002"></a><h2>描述</h2>
<p><tt class="COMMAND">UPDATE</tt> 改变满足条件的所有行中指定的字段值。只在 <tt class="LITERAL">SET</tt> 子句中出现需要修改的行，没有出现的其他字段保持它们原来的数值。</p>
<p>缺省时，<tt class="COMMAND">UPDATE</tt> 将更新所声明的表和所有子表的记录。如果你希望只更新所声明的表，应该使用 <tt class="LITERAL">ONLY</tt> 子句。</p>
<p>使用同一数据库里其它表的信息来更新一个表有两种方法：使用子查询，或者在 <tt class="LITERAL">FROM</tt> 子句里声明另外一个表。哪个方法更好取决于具体的环境。</p>
<p>可选的 <tt class="LITERAL">RETURNING</tt> 子句将导致 <tt class="COMMAND">UPDATE</tt> 基于每个被更新的行计算返回值。任何 <tt class="LITERAL">FROM</tt> 中使用的字段都可以用于计算。计算的时候使用刚刚被更新过的字段新值。<tt class="LITERAL">RETURNING</tt> 列表的语法与 <tt class="COMMAND">SELECT</tt> 的输出列表相同。</p>
<p>要修改表，你必须对它有 <tt class="LITERAL">UPDATE</tt> 权限，同样对 <tt class="REPLACEABLE"><i>expressions</i></tt> 或 <tt class="REPLACEABLE"><i>condition</i></tt> 条件里提到的任何表也要有 <tt class="LITERAL">SELECT</tt> 权限。</p>
</div>
<div class="REFSECT1"><a name="AEN55023"></a><h2>参数</h2>
<div class="VARIABLELIST">
<dl>
<dt><tt class="REPLACEABLE"><i>table</i></tt></dt>
<dd><p>现存表的名称(可以有模式修饰)</p></dd>
<dt><tt class="REPLACEABLE"><i>alias</i></tt></dt>
<dd><p>目标表的别名。如果指定了别名，那么它将完全遮盖表的本名。例如，给定 <tt class="LITERAL">UPDATE foo AS f</tt> 之后，剩余的 <tt class="COMMAND">UPDATE</tt> 语句必须用 <tt class="LITERAL">f</tt> 而不是 <tt class="LITERAL">foo</tt> 引用这个表。</p></dd>
<dt><tt class="REPLACEABLE"><i>column</i></tt></dt>
<dd><p>表 <tt class="REPLACEABLE"><i>table</i></tt> 中的字段名。必要时，字段名可以用子域名或者数组下标修饰。不要在指定字段名的时候加上表名字。比如 <tt class="LITERAL">UPDATE tab SET tab.col = 1</tt> 就是错误的。</p></dd>
<dt><tt class="REPLACEABLE"><i>expression</i></tt></dt>
<dd><p>给字段赋值的有效值或表达式。表达式可以使用这个或其它字段更新前的旧值。</p></dd>
<dt><tt class="LITERAL">DEFAULT</tt></dt>
<dd><p>把字段设置为它的缺省值，如果没有缺省表达式，那么就是 NULL</p></dd>
<dt><tt class="REPLACEABLE"><i>fromlist</i></tt></dt>
<dd><p>一个表表达式的列表，允许来自其它表中的字段出现在 <tt class="LITERAL">WHERE</tt> 条件里。这个类似于可以在一个 <tt class="COMMAND">SELECT</tt> 语句的 <a href="sql-select.html#SQL-FROM"><i><i>FROM</i> 子句</i></a>里声明表列表。请注意目标表绝对不能出现在 <tt class="REPLACEABLE"><i>fromlist</i></tt> 里，除非你是在使用一个自连接(此时它必须以 <tt class="REPLACEABLE"><i>fromlist</i></tt> 的别名出现)。</p></dd>
<dt><tt class="REPLACEABLE"><i>condition</i></tt></dt>
<dd><p>一个返回 <tt class="TYPE">boolean</tt> 结果的表达式。只有这个表达式返回 <tt class="LITERAL">true</tt> 的行才会被更新。</p></dd>
<dt><tt class="REPLACEABLE"><i>output_expression</i></tt></dt>
<dd><p>在所有需要更新的行都被更新之后，<tt class="COMMAND">UPDATE</tt> 命令用于计算返回值的表达式。这个表达式可以使用任何 <tt class="REPLACEABLE"><i>table</i></tt> 以及 <tt class="LITERAL">FROM</tt> 中列出的表的字段。写上 <tt class="LITERAL">*</tt> 表示返回所有字段。</p></dd>
<dt><tt class="REPLACEABLE"><i>output_name</i></tt></dt>
<dd><p>字段的返回名称</p></dd>
</dl>
</div>
</div>
<div class="REFSECT1"><a name="AEN55088"></a><h2>输出</h2>
<p>成功完成后，<tt class="COMMAND">UPDATE</tt> 返回形如</p>
<pre class="SCREEN">UPDATE <tt class="REPLACEABLE"><i>count</i></tt></pre>
<p>的命令标签。<tt class="REPLACEABLE"><i>count</i></tt> 是更新的行数。如果为 0 则表示没有符合 <tt class="REPLACEABLE"><i>condition</i></tt> 的行(这个不认为是错误)。</p>
<p>如果 <tt class="COMMAND">UPDATE</tt> 包含 <tt class="LITERAL">RETURNING</tt> 子句，那么返回的结果将类似于包含 <tt class="LITERAL">RETURNING</tt> 字段和表达式列表的 <tt class="COMMAND">SELECT</tt> 语句，只不过返回结果是基于被更新的行而已。</p>
</div>
<div class="REFSECT1"><a name="AEN55102"></a><h2>注意</h2>
<p>在出现 <tt class="LITERAL">FROM</tt> 子句的时候，实际上发生的事情是目标表和 <tt class="REPLACEABLE"><i>fromlist</i></tt> 里提到的表连接在一起，并且每个连接输出行都代表一个目标表的更新操作。在使用 <tt class="LITERAL">FROM</tt> 的时候，你应该保证连接为每个需要修改的行最多生成一个输出行。换句话说，一个目标行不应该和超过一行来自其它表的数据行连接。如果它连接了多于一个行，那么连接行里面将会只有一行用于更新目标行，但是究竟使用哪行是很难预期的事情。</p>
<p>因为这个不确定性，只再子查询里面引用其它表是安全的，尽管通常更难读并且比使用连接也更慢些。</p>
</div>
<div class="REFSECT1"><a name="AEN55109"></a><h2>例子</h2>
<p>把表 <tt class="STRUCTNAME">films</tt> 里的字段 <tt class="STRUCTFIELD">kind</tt> 里的词 <tt class="LITERAL">Drama</tt> 用 <tt class="LITERAL">Dramatic</tt> 代替：</p>
<pre class="PROGRAMLISTING">UPDATE films SET kind = 'Dramatic' WHERE kind = 'Drama';</pre>
<p>调整表 <tt class="STRUCTNAME">weather</tt> 中的某行的温度并把该行的降水量设置为缺省值：</p>
<pre class="PROGRAMLISTING">UPDATE weather SET temp_lo = temp_lo+1, temp_hi = temp_lo+15, prcp = DEFAULT
  WHERE city = 'San Francisco' AND date = '2003-07-03';</pre>
<p>做同样的事情并返回更新后的条目：</p>
<pre class="PROGRAMLISTING">UPDATE weather SET temp_lo = temp_lo+1, temp_hi = temp_lo+15, prcp = DEFAULT
  WHERE city = 'San Francisco' AND date = '2003-07-03'
  RETURNING temp_lo, temp_hi, prcp;</pre>
<p>使用另一种字段列表语法来做同样的事情：</p>
<pre class="PROGRAMLISTING">UPDATE weather SET (temp_lo, temp_hi, prcp) = (temp_lo+1, temp_lo+15, DEFAULT)
  WHERE city = 'San Francisco' AND date = '2003-07-03';</pre>
<p>增加负责 Acme 公司客户的销售员的销售计数，使用 <tt class="LITERAL">FROM</tt> 子句语法：</p>
<pre class="PROGRAMLISTING">UPDATE employees SET sales_count = sales_count + 1 FROM accounts
  WHERE accounts.name = 'Acme Corporation'
  AND employees.id = accounts.sales_person;</pre>
<p>使用 <tt class="LITERAL">WHERE</tt> 子句里的子查询执行同样的操作：</p>
<pre class="PROGRAMLISTING">UPDATE employees SET sales_count = sales_count + 1 WHERE id =
  (SELECT sales_person FROM accounts WHERE name = 'Acme Corporation');</pre>
<p>试图带着库存量插入一个新的库存项。如果该项存在，则更新现有项的库存数。要做这件事情而又不使整个事务失效，使用保留点。</p>
<pre class="PROGRAMLISTING">BEGIN;
-- 其它操作
SAVEPOINT sp1;
INSERT INTO wines VALUES('Chateau Lafite 2003', '24');
-- 假设上面因为一个唯一键字违例而失效，
-- 因此现在发出这些命令：
ROLLBACK TO sp1;
UPDATE wines SET stock = stock + 24 WHERE winename = 'Chateau Lafite 2003';
-- 继续其它操作，最后
COMMIT;</pre>
</div>
<div class="REFSECT1"><a name="AEN55132"></a><h2>兼容性</h2>
<p>这条命令遵循 SQL 标准。只是 <tt class="LITERAL">FROM</tt> 和 <tt class="LITERAL">RETURNING</tt> 子句是 PostgreSQL 扩展。</p>
<p>标准的字段列表语法允许从行值表达式指定字段列表，比如一个子查询：</p>
<pre class="PROGRAMLISTING">UPDATE accounts SET (contact_last_name, contact_first_name) =
    (SELECT last_name, first_name FROM salesmen
     WHERE salesmen.id = accounts.sales_id);</pre>
<p>这个功能目前尚未实现：源必须是一个独立的表达式。</p>
<p>有些其它数据库系统提供一个 <tt class="LITERAL">FROM</tt> 选项，在这个选项下，认为目标表会再次在 <tt class="LITERAL">FROM</tt> 里列出。这不是 PostgreSQL 解析 <tt class="LITERAL">FROM</tt> 的方式。移植使用这类扩展的应用时要注意。</p>
</div>
<div>
<hr align="LEFT" width="100%">
<table summary="Footer navigation table" width="100%" border="0" cellpadding="0" cellspacing="0">
<tr><td width="33%" align="left" valign="top"><a href="sql-unlisten.html" accesskey="P">后退</a></td><td width="34%" align="center" valign="top"><a href="index.html" accesskey="H">首页</a></td><td width="33%" align="right" valign="top"><a href="sql-vacuum.html" accesskey="N">前进</a></td></tr>
<tr><td width="33%" align="left" valign="top">UNLISTEN</td><td width="34%" align="center" valign="top"><a href="sql-commands.html" accesskey="U">上一级</a></td><td width="33%" align="right" valign="top">VACUUM</td></tr>
</table>
</div>
</body></html>